#include "GamePanel.h"
#include "PlayHand.h"
#include "ui_GamePanel.h"
#include <QMouseEvent>
#include <QPainter>
#include <QRandomGenerator>
#include <QTimer>

GamePanel::GamePanel(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::GamePanel)
{
    ui->setupUi(this);

    // 背景图、标题、固定大小
    int num = QRandomGenerator::global()->bounded(10);//0-9
    QString path = QString(":/images/background-%1.png").arg(num+1);
    m_bkImage.load(path);
    this->setWindowTitle("欢乐斗地主");
    this->setFixedSize(1000,650);
    // 实例化游戏控制类
    gameControlInit();
    // 初始化玩家得分(更新)
    updatePlayerScore();
    // 切割游戏中的图片
    initCardMap();
    // 初始化游戏中的按钮
    initButtonGroup();
    // 初始化玩家在窗口中的上下文环境（牌和头像的位置）
    initPlayerContext();
    // 扑克牌场景初始化
    initGameScene();
    //初始化倒计时窗口
    initCountDown();

    //实例化定时器
    m_timer = new QTimer(this);
    connect(m_timer,&QTimer::timeout,this,&GamePanel::onDiapatchCard);
    //实例化动画对象
    m_animation = new AnimationWindow(this);
    m_bgm = new BGMContrl(this);
}

GamePanel::~GamePanel()
{
    delete ui;
}

void GamePanel::gameControlInit()
{
    m_gameCtl = new GameControl(this);
    m_gameCtl->playerInit();//调用则创建出了三个玩家的实例化对象
    //得到三个玩家的实例对象(顺序：左侧，右侧，玩家)
    Robot* leftRobot = m_gameCtl->leftRobot();
    Robot* rightRobot = m_gameCtl->rightRobot();
    UserPlayer* user = m_gameCtl->userPlayer();
    m_playerList << leftRobot << rightRobot << user;
    connect(m_gameCtl,&GameControl::playerStatusChange, this,&GamePanel::onPlayerStatusChanged);
    connect(m_gameCtl,&GameControl::notifyGradLordBet,this,&GamePanel::onGrabLordBet);
    connect(m_gameCtl,&GameControl::gameStatusChanged,this,&GamePanel::gameStatusPreces);
    connect(m_gameCtl,&GameControl::notifyPlayHand,this,&GamePanel::onDisposePlayHand);

    connect(leftRobot,&Robot::notifyPickCards,this,&GamePanel::disposCard);
    connect(rightRobot,&Robot::notifyPickCards,this,&GamePanel::disposCard);
    connect(user,&Robot::notifyPickCards,this,&GamePanel::disposCard);
}

void GamePanel::updatePlayerScore()
{
    ui->scorePanel->setScores(m_playerList[0]->score(), m_playerList[1]->score(), m_playerList[2]->score());
}

void GamePanel::initCardMap()
{
    //加载大图
    QPixmap pixmap(":/images/card.png");
    //计算每张图片的大小
    m_cardSize.setWidth((pixmap.width() / 13));
    m_cardSize.setHeight((pixmap.height() / 5));

    //背景图
    m_cardBackImg = pixmap.copy(2*m_cardSize.width(),4*m_cardSize.height(),m_cardSize.width(),m_cardSize.height());
    //扑克牌正常花色
    for(int i = 0, suit = Card::Suit_Begin + 1; suit < Card::Suit_End; ++suit,++i){
        for(int j = 0, pt = Card::Card_Begin + 1; pt < Card::Card_SJ; ++pt,++j){
            Card card((Card::CardPoint)pt, (Card::CardSuit)suit);
            //裁剪图片
            cropImage(pixmap, j*m_cardSize.width(),i*m_cardSize.height(),card);
        }
    }

    //大小王
    Card c;
    c.setPoint(Card::Card_SJ);
    c.setSuit(Card::Suit_Begin);
    cropImage(pixmap, 0, 4*m_cardSize.height(), c);

    c.setPoint(Card::Card_BJ);
    c.setSuit(Card::Suit_Begin);
    cropImage(pixmap,m_cardSize.width(),4*m_cardSize.height(),c);
}

void GamePanel::cropImage(QPixmap &pix, int x, int y,Card& card)
{
    QPixmap sub = pix.copy(x,y,m_cardSize.width(),m_cardSize.height());
    CardPanel* panel = new CardPanel(this);
    panel->setImage(sub,m_cardBackImg);
    panel->setCard(card);
    panel->hide();
    m_cardMap.insert(card, panel);//保存在映射中
    connect(panel,&CardPanel::cardSelected,this, &GamePanel::onCardSelected);
}

void GamePanel::initButtonGroup()
{
    ui->btnGroup->initButtons();
    ui->btnGroup->selectPanel(ButtonGroup::Start);
    //连接信号（开始游戏、出牌，放弃出牌，叫地主得分）
    connect(ui->btnGroup,&ButtonGroup::startGame,this,[=](){
        //界面的初始化(隐藏按钮/分数)
        ui->btnGroup->selectPanel(ButtonGroup::Empty);
        m_gameCtl->clearPlayerScore();
        updatePlayerScore();
        //修改游戏的状态->发牌
        gameStatusPreces(GameControl::DispatchCard);
        //播放背景音乐
        m_bgm->startBGM(80);
    });
    connect(ui->btnGroup,&ButtonGroup::playHand,this,&GamePanel::onUserPlayHand);
    connect(ui->btnGroup,&ButtonGroup::pass,this,&GamePanel::onUserPass);
    connect(ui->btnGroup,&ButtonGroup::betPoint,this,[=](int bet){
        m_gameCtl->userPlayer()->grabLordBet(bet);
        ui->btnGroup->selectPanel(ButtonGroup::Empty);
    });
}

void GamePanel::initPlayerContext()
{
    // 1. 确定每个玩家放置扑克牌的区域
    const QRect cardsRect[] = {
        QRect(90, 130, 100, height() - 200),                 //左侧机器人
        QRect(rect().right() - 190, 130, 100, height() - 200),//右侧机器人
        QRect(250, rect().bottom() - 120, width() - 500, 100)//当前玩家
    };
    // 2. 玩家出牌的区域
    const QRect playHandRect[] = {
        QRect(260, 150, 100, 100),                           //左侧机器人
        QRect(rect().right() - 360, 150, 100, 100),          //右侧机器人
        QRect(150, rect().bottom() - 290, width() - 300, 105)//当前玩家
    };
    // 3. 玩家头像显示的区域
    const QPoint roleImgPos[] = {
        QPoint(cardsRect[0].left() - 80, cardsRect[0].height() / 2 + 20),//左侧机器人
        QPoint(cardsRect[1].right() + 10, cardsRect[1].height() / 2 + 20),//右侧机器人
        QPoint(cardsRect[2].right() - 10, cardsRect[2].top() - 10)        //当前玩家
    };
    //存到上下文Map中
    int index = m_playerList.indexOf(m_gameCtl->userPlayer());//获取玩家的索引
    for(int i = 0;i<m_playerList.size();++i){
        PlayerContext context;
        context.align = (i==index) ? Horizontal : Vertical;
        context.isFrontSide = (i==index) ? true : false;
        context.cardRect = cardsRect[i];
        context.playHandRect = playHandRect[i];
        //提示信息是标签，进行初始化和设置大小、暂时隐藏，显示在出牌区的中心位置
        context.info = new QLabel(this);
        context.info->resize(160,98);
        context.info->hide();//暂时隐藏
        QRect rect = playHandRect[i];
        QPoint pt(rect.left()+(rect.width()-context.info->width()) / 2,
                  rect.top() + (rect.height() - context.info->height()) / 2);
        context.info->move(pt);
        //玩家的头像
        context.roleImg = new QLabel(this);
        context.roleImg->resize(84,120);
        context.roleImg->hide();
        context.roleImg->move(roleImgPos[i]);
        //玩家打出的牌为空
        m_contextMap.insert(m_playerList.at(i),context);
    }
}

void GamePanel::initGameScene()
{
    // 1. 发牌区扑克牌
    m_baseCard = new CardPanel(this);
    m_baseCard->setImage(m_cardBackImg,m_cardBackImg);
    // 2. 发牌过程中移动的扑克牌
    m_moveCard = new CardPanel(this);
    m_moveCard->setImage(m_cardBackImg,m_cardBackImg);
    // 3. 最后的三张底牌（用于显示）
    for(int i = 0;i<3 ;++i){
        CardPanel* panel = new CardPanel(this);
        panel->setImage(m_cardBackImg,m_cardBackImg);
        m_last3Card.push_back(panel);
        panel->hide();
    }
    //中央显示扑克牌的位置
    m_baseCardPos = QPoint((width() - m_cardSize.width()) / 2,
                           ((height() - m_cardSize.height())/2 - 100));
    m_baseCard->move(m_baseCardPos);
    m_moveCard->move(m_baseCardPos);
    //最后三张底牌的位置
    int base = (width() - 3 * m_cardSize.width() - 20) / 2;
    for(int i = 0;i<3;++i){
        m_last3Card[i]->move(base + (m_cardSize.width() + 10) * i, 10);
    }
}

void GamePanel::gameStatusPreces(GameControl::GameStatus status)
{
    // 记录游戏状态
    m_gameStatus = status;
    // 处理游戏状态
    switch (status) {
    case GameControl::DispatchCard://发牌
        startDispatchCard();
        break;
    case GameControl::CallingLord://叫地主
    {
        // 取出三张底牌的数据
        CardList last3Card = m_gameCtl->surPlusCards().toCardList();
        // 给三张底牌设置图片
        for(int i = 0;i<last3Card.size();++i){
            QPixmap front = m_cardMap[last3Card.at(i)]->image();
            m_last3Card[i]->setImage(front,m_cardBackImg);
            m_last3Card[i]->hide();
        }
        //开始叫地主
        m_gameCtl->startLordCard();

        break;
    }
    case GameControl::GameStatus::PlayingHand://出牌
        //隐藏发牌区的底牌和移动的牌
        m_baseCard->hide();
        m_moveCard->hide();
        //将地主牌显示出来
        for(int i = 0;i<m_last3Card.size();++i){
            m_last3Card.at(i)->show();
        }
        //将各个玩家抢地主的提示信息隐藏掉
        for(int i = 0;i<m_playerList.size();i++){
            PlayerContext& context = m_contextMap[m_playerList.at(i)];
            context.info->hide();
            //把各个玩家的头像显示出来
            Player* player = m_playerList.at(i);
            QPixmap pixmap = loadRoleImage(player->sex(),player->direction(),player->role());
            context.roleImg->setPixmap(pixmap);
            context.roleImg->show();
        }
        break;
    default:
        break;
    }
}

void GamePanel::startDispatchCard()
{
    //每局开始前，重置每张卡牌的属性
    for(auto it = m_cardMap.begin(); it != m_cardMap.end(); ++it){
        it.value()->setSelected(false);//取消每张牌的选中状态
        it.value()->setFrontSide(true);//每张牌都显示正面
        it.value()->hide();
    }
    //将展示的地主牌隐藏
    for(int i = 0;i<m_last3Card.size();++i){
        m_last3Card.at(i)->hide();
    }
    //重置所有玩家的上下文信息
    int index = m_playerList.indexOf(m_gameCtl->userPlayer());
    for(int i = 0; i < m_playerList.size(); ++i){
        m_contextMap[m_playerList.at(i)].lastCards.clear();//清空记录的刚打出的牌
        m_contextMap[m_playerList.at(i)].info->hide();//隐藏提示信息
        m_contextMap[m_playerList.at(i)].roleImg->hide();//隐藏头像信息
        m_contextMap[m_playerList.at(i)].isFrontSide = (i==index) ? true : false;
    }
    //清空玩家手里的牌的数据
    m_gameCtl->resetCardData();
    //显示窗口中央的底牌
    m_baseCard->show();
    //隐藏按钮面板
    ui->btnGroup->selectPanel(ButtonGroup::Empty);
    //启动定时器（用来动态发牌效果）
    m_timer->start(10);
    //播放背景音乐
    m_bgm->playAssistMusic(BGMContrl::Dispatch);
}

void GamePanel::cardMoveStep(Player* player, int curPos)
{
    //得到每个玩家的扑克牌的展示区域
    QRect cardRect = m_contextMap[player].cardRect;
    //计算每个玩家的单元步长
    const int unit[] = {
        (m_baseCardPos.x()-cardRect.right()) / 100,//左侧机器人
        (cardRect.left()-m_baseCardPos.x()) / 100,//右侧机器人
        (cardRect.top()-m_baseCardPos.y()) / 100//玩家
    };
    //每次窗口移动时的实时位置
    const QPoint pos[] = {
        QPoint(m_baseCardPos.x() - curPos*unit[0], m_baseCardPos.y()),//左侧机器人
        QPoint(m_baseCardPos.x() + curPos*unit[1], m_baseCardPos.y()),//右侧机器人
        QPoint(m_baseCardPos.x(), m_baseCardPos.y() + curPos*unit[2])//玩家
    };
    //移动扑克牌窗口
    int index = m_playerList.indexOf(player);
    m_moveCard->move(pos[index]);

    //临界状态的判定（开始和结束的显示或隐藏）
    if(curPos == 0){
        m_moveCard->show();
    }
    if(curPos == 100){
        m_moveCard->hide();
    }
}

void GamePanel::disposCard(Player *player, const Cards &cards)
{
    Cards& myCard = const_cast<Cards&>(cards);
    CardList list = myCard.toCardList();
    for(int i = 0;i<list.size();++i){
        CardPanel* panel = m_cardMap[list.at(i)];
        //设置窗口的所有者
        panel->setOwner(player);
    }
    //更新扑克牌在窗口中的显示
    updatePlayerCards(player);
}

void GamePanel::updatePlayerCards(Player *player)
{
    Cards cards = player->cards();
    CardList list = cards.toCardList();
    m_cardRect = QRect();
    m_userCards.clear();
    //取出展示扑克牌区域
    int cardSpace = 20;
    QRect cardsRect = m_contextMap[player].cardRect;
    for(int i = 0;i<list.size();++i){
        CardPanel* panel = m_cardMap[list.at(i)];
        panel->show();
        panel->raise();//让当前的窗口位于最上层显示
        panel->setFrontSide(m_contextMap[player].isFrontSide);
        //水平展示或垂直展示
        if(m_contextMap[player].align == Horizontal){
            int leftx = cardsRect.left() + (cardsRect.width() - (list.size() - 1) * cardSpace - panel->width()) / 2;
            int topy = cardsRect.top() + (cardsRect.height() - m_cardSize.height()) / 2;
            if(panel->isSelected()){
                topy -= 10;
            }
            panel->move(leftx + cardSpace * i, topy);
            m_cardRect = QRect(leftx, topy, cardSpace * i + m_cardSize.width(), m_cardSize.height());
            int curWidth = 0;if(list.size() -1 == i){
                curWidth = m_cardSize.width();
            }else{
                curWidth = cardSpace;
            }
            QRect cardRect(leftx + cardSpace * i, topy, curWidth,m_cardSize.height());
            m_userCards.insert(panel, cardRect);
        }else{
            int leftx = cardsRect.left() + (cardsRect.width() - m_cardSize.width()) / 2;
            int topy = cardsRect.top() + (cardsRect.height() - (list.size() - 1) * cardSpace - panel->height()) / 2;
            panel->move(leftx, topy + cardSpace * i);
        }
    }

    //显示玩家打出的牌
    //得到当前玩家的出牌区域以及打出去的牌
    QRect playCardRect = m_contextMap[player].playHandRect;
    Cards lastCards = m_contextMap[player].lastCards;
    if(!lastCards.isEmpty()){
        int playSpace = 24;
        CardList lastCardList = lastCards.toCardList();
        //遍历
        CardList::ConstIterator itplayed = lastCardList.constBegin();
        for(int i = 0;itplayed != lastCardList.constEnd(); ++itplayed,i++){
            CardPanel* panel = m_cardMap[*itplayed];
            panel->setFrontSide(true);
            panel->raise();
            // 将打出的牌移动到出牌区
            if(m_contextMap[player].align == Horizontal){
                int leftBase = playCardRect.left() + (playCardRect.width() - (lastCardList.size() - 1)*playSpace - panel->width()) /2;
                int top = playCardRect.top() + (playCardRect.height() - panel->height()) /2;
                panel->move(leftBase + i * playSpace, top);

            }else{
                int leftBase = playCardRect.left() +(playCardRect.width() - panel->height()) /2;
                int top = playCardRect.top();
                panel->move(leftBase, top + i * playSpace);
            }
            panel->show();
        }
    }
}

void GamePanel::onDiapatchCard()
{
    //记录扑克牌的位置
    static int curMovePos = 0;
    //当前给哪一个玩家发牌
    Player* curPlayer = m_gameCtl->currentPlayer();
    //发到底后切换玩家
    if(curMovePos >= 100){
        //给玩家发一张牌
        Card card = m_gameCtl->takeOneCard();
        curPlayer->storeDispatchCard(card);
        Cards cs(card);
        //disposCard(curPlayer, cs);
        //切换玩家
        m_gameCtl->setCurrentPlayer(curPlayer->nextPlayer());
        curMovePos = 0;
        //继续开始动画
        cardMoveStep(curPlayer,curMovePos);
        //判断牌是否值剩下三张
        if(m_gameCtl->surPlusCards().cardCount() == 3){
            //停止定时器
            m_timer->stop();
            //切换游戏的状态
            gameStatusPreces(GameControl::CallingLord);
            //终止发牌
            m_bgm->stopAssisMusic();
            return;
        }
    }
    //移动扑克牌
    cardMoveStep(curPlayer,curMovePos);
    curMovePos += 15;
}

void GamePanel::onPlayerStatusChanged(Player *player, GameControl::PlayerStatus status)
{
    switch (status) {
    case GameControl::ThinkingForCallLord:
        if(player == m_gameCtl->userPlayer()){
            ui->btnGroup->selectPanel(ButtonGroup::CallLord, m_gameCtl->playerMaxBet());
        }
        break;
    case GameControl::PlayerStatus::ThinkingForPlayHand:
    {
        //隐藏上一轮打出的牌
        hidePlayerDropCards(player);
        if(player == m_gameCtl->userPlayer()){
            //取出出牌玩家的对象
            Player* pendPlayer = m_gameCtl->pendPlayer();
            if(pendPlayer == m_gameCtl->userPlayer() || pendPlayer == nullptr){
                ui->btnGroup->selectPanel(ButtonGroup::PlayCard);
            }else{
                ui->btnGroup->selectPanel(ButtonGroup::PassOrPlay);
            }
        }else{
            ui->btnGroup->selectPanel(ButtonGroup::Empty);
        }
        break;
    }
    case GameControl::PlayerStatus::Winning:
        m_bgm->stopBGM();
        m_contextMap[m_gameCtl->leftRobot()].isFrontSide = true;
        m_contextMap[m_gameCtl->rightRobot()].isFrontSide = true;
        updatePlayerCards(m_gameCtl->leftRobot());
        updatePlayerCards(m_gameCtl->rightRobot());
        //更新玩家的得分
        updatePlayerScore();
        m_gameCtl->setCurrentPlayer(player);
        showEndingScorePanel();
        break;
    default:
        break;
    }
}

void GamePanel::onGrabLordBet(Player *player, int bet, bool flag)
{
    // 显示抢地主的文字提示
    PlayerContext context = m_contextMap[player];
    if(bet == 0){
        context.info->setPixmap(QPixmap(":/images/buqinag.png"));
    }else{
        if(flag){//说明是有玩家第一次抢地主
            context.info->setPixmap(QPixmap(":/images/jiaodizhu.png"));
        }else{
            context.info->setPixmap(QPixmap(":/images/qiangdizhu.png"));
        }
        //显示玩家叫地主的分数
        showAnimation(Bet,bet);
    }
    context.info->show();
    //播放背景音乐
    m_bgm->playerRobLordMousic(bet, (BGMContrl::RoleSex)player->sex(), flag);
}

void GamePanel::showAnimation(AnimationType type, int bet)
{
    switch (type) {
    case AnimationType::LianDui:
    case AnimationType::ShunZi:
        m_animation->setFixedSize(250,150);
        m_animation->move((width()-m_animation->width())/2, 200);
        m_animation->showSequence((AnimationWindow::Type)type);
        break;
    case AnimationType::Plane:
        m_animation->setFixedSize(800,75);
        m_animation->move((width()-m_animation->width())/2, 200);
        m_animation->showPlane();
        break;
    case AnimationType::JokerBomb:
        m_animation->setFixedSize(250,200);
        m_animation->move((width()-m_animation->width())/2, (height() - m_animation->height()) /2 - 70);
        m_animation->showJokerBomb();
        break;
    case AnimationType::Bomb:
        m_animation->setFixedSize(180,200);
        m_animation->move((width()-m_animation->width())/2, (height() - m_animation->height()) /2 - 70);
        m_animation->showBomb();
        break;
    case AnimationType::Bet:
        m_animation->setFixedSize(160,98);
        m_animation->move((width()-m_animation->width())/2, (height()-m_animation->height())/2-230);
        m_animation->showBetScore(bet);
        break;
    default:
        break;
    }
    m_animation->show();
}

void GamePanel::onDisposePlayHand(Player *player, Cards& cards)
{
    //记录玩家打出的牌
    QMap<Player*, PlayerContext>::iterator it = m_contextMap.find(player);
    it->lastCards = cards;
    //根据出牌的牌型播放游戏特效
    PlayHand hand(cards);
    PlayHand::HandType type = hand.handType();
    if(type == PlayHand::Hand_Plane || type == PlayHand::Hand_Plane_Two_Single || type == PlayHand::Hand_Plane_Two_Pair){
        showAnimation(Plane);
    }else if(type == PlayHand::Hand_Seq_Pair){
        showAnimation(LianDui);
    }else if(type == PlayHand::Hand_Seq_Single){
        showAnimation(ShunZi);
    }else if(type == PlayHand::Hand_Bomb){
        showAnimation(Bomb);
    }else if(type == PlayHand::Hand_Bomb_Jokers){
        showAnimation(JokerBomb);
    }
    //如果玩家打出的是空牌（不出牌），显示提示信息
    if(cards.isEmpty()){
        it->info->setPixmap(QPixmap(":/images/pass.png"));
        it ->info->show();
        m_bgm->playPassMusic((BGMContrl::RoleSex)player->sex());
    }else{
        if(m_gameCtl->pendPlayer() == player || m_gameCtl->pendPlayer() == nullptr){
            m_bgm->playCardMusic(cards, true,(BGMContrl::RoleSex)player->sex());
        }else{
            m_bgm->playCardMusic(cards,false,(BGMContrl::RoleSex)player->sex());
        }
    }
    //更新玩家剩余的牌
    updatePlayerCards(player);
    //播放提示音乐
    if(player->cards().cardCount() == 2){
        m_bgm->playLastMusic(BGMContrl::Last2, (BGMContrl::RoleSex)player->sex());
    }else if(player->cards().cardCount() == 1){
        m_bgm->playLastMusic(BGMContrl::Last1, (BGMContrl::RoleSex)player->sex());
    }
}

void GamePanel::hidePlayerDropCards(Player *player)
{
    QMap<Player*, PlayerContext>::iterator it = m_contextMap.find(player);
    if(it != m_contextMap.end()){
        if(it->lastCards.isEmpty()){
            it->info->hide();
        }else{
            // 将玩家打出去的牌变为Card类型
            CardList list = it->lastCards.toCardList();
            for(auto last = list.begin(); last != list.end();++last){
                m_cardMap[*last]->hide();
            }
        }
        it->lastCards.clear();
    }
}

QPixmap GamePanel::loadRoleImage(Player::Sex sex, Player::Direction direct, Player::Role role)
{
    //找到相关的图片（男地主、男农民，女地主，女农民）
    QVector<QString> lordMan;
    QVector<QString> lordWoman;
    QVector<QString> farmerMan;
    QVector<QString> farmerWoman;
    lordMan << ":/images/lord_man_1.png" << ":/images/lord_man_2.png";
    lordWoman << ":/images/lord_woman_1.png" << ":/images/lord_woman_2.png";
    farmerMan << ":/images/farmer_man_1.png" << ":/images/farmer_man_2.png";
    farmerWoman << ":/images/farmer_woman_1.png" << ":/images/farmer_woman_2.png";

    //加载图片 QImage（提供了镜像的功能，QPixmap没有）
    QImage image;
    int random = QRandomGenerator::global()->bounded(2);
    if(sex == Player::Man && role == Player::Lord){
        image.load(lordMan[random]);
    }else if(sex == Player::Man && role == Player::Farmer){
        image.load(farmerMan[random]);
    }else if(sex == Player::Woman && role == Player::Lord){
        image.load(lordWoman[random]);
    }else if(sex == Player::Woman && role == Player::Farmer){
        image.load(farmerWoman[random]);
    }
    QPixmap pixmap;
    if(direct == Player::Left){
        pixmap = QPixmap::fromImage(image);
    }else{
        pixmap = QPixmap::fromImage(image.mirrored(true,false));
    }
    return pixmap;
}

void GamePanel::onCardSelected(Qt::MouseButton button)
{
    //判断游戏状态（不是出牌状态则会忽略）
    if(m_gameStatus == GameControl::DispatchCard || m_gameStatus == GameControl::CallingLord){
        return;
    }
    //判断这个牌是不是用户玩家的
    CardPanel* panel = static_cast<CardPanel*>(sender());
    if(panel->owner() != m_gameCtl->userPlayer()){
        return;
    }
    //保存当前选中的牌的窗口对象
    m_curSelCard = panel;
    //判断是鼠标左键还是右键
    if(button == Qt::LeftButton){
        //设置选中状态
        panel->setSelected(!panel->isSelected());
        //更新扑克牌的显示
        updatePlayerCards(panel->owner());
        //保存或删除扑克牌对象
        QSet<CardPanel*>::const_iterator it = m_selectCard.find(panel);
        if(it == m_selectCard.constEnd()){
            m_selectCard.insert(panel);
        }else{
            m_selectCard.erase(it);
        }
        m_bgm->playAssistMusic(BGMContrl::SelectCard);

    }else if(button == Qt::RightButton){
        // 调用出牌按钮槽函数
        onUserPlayHand();
    }
}

void GamePanel::onUserPlayHand()
{
    //判断是不是出牌阶段
    if(m_gameStatus != GameControl::PlayingHand){
        return;
    }
    //判断当前玩家是否是用户
    if(m_gameCtl->currentPlayer() != m_gameCtl->userPlayer()){
        return;
    }
    //判断出的是不是空牌
    if(m_selectCard.isEmpty()){
        return;
    }
    //得到牌型
    Cards cs;
    for(auto it = m_selectCard.begin(); it!=m_selectCard.end(); ++it){
        Card card = (*it)->card();
        cs.add(card);
    }
    PlayHand hand(cs);
    PlayHand::HandType type = hand.handType();
    if(type == PlayHand::Hand_Unknown){
        return;
    }
    if(m_gameCtl->pendPlayer() != m_gameCtl->userPlayer()){
        Cards cards = m_gameCtl->pendCards();
        //能不能压住上家的牌
        if(!hand.canBeat(PlayHand(cards))){
            return;
        }

    }
    m_countDown->stopCountDown();
    //通过玩家对象出牌
    m_gameCtl->userPlayer()->playHand(cs);
    //清空容器
    m_selectCard.clear();
}

void GamePanel::onUserPass()
{
    m_countDown->stopCountDown();
    //判断是不是用户玩家
    Player* curPlayer = m_gameCtl->currentPlayer();
    Player* userPlayer = m_gameCtl->userPlayer();
    if(curPlayer != userPlayer){
        return;
    }
    //如果上一次出牌的玩家是用户玩家，就不能放弃
    Player* pendPlayer = m_gameCtl->pendPlayer();
    if(pendPlayer == userPlayer || pendPlayer == nullptr){
        return;
    }
    //打出一个空的Cards对象
    Cards empty;
    userPlayer->playHand(empty);
    //清空用户已经选择的牌
    for(auto it = m_selectCard.begin(); it != m_selectCard.end(); ++it){
        (*it)->setSelected(false);
    }
    m_selectCard.clear();
    //对待出牌区域进行更新
    updatePlayerCards(userPlayer);
}

void GamePanel::showEndingScorePanel()
{
    bool isLord = m_gameCtl->userPlayer()->role() == Player::Lord ? true : false;
    bool isWin = m_gameCtl->userPlayer()->isWin();
    EndingPanel* panel = new EndingPanel(isLord,isWin,this);
    panel->show();
    panel->move((width() - panel->width())/2, -panel->height());
    panel->setPlayerScore(m_gameCtl->leftRobot()->score(),m_gameCtl->rightRobot()->score(),m_gameCtl->userPlayer()->score());
    if(isWin){
        m_bgm->playEndingMusic(true);
    }else{
        m_bgm->playEndingMusic(false);
    }
    QPropertyAnimation* animation = new QPropertyAnimation(panel, "geometry",this);
    //设置动画的持续时间
    animation->setDuration(1500);
    //设置窗口的起始位置和终止位置
    animation->setStartValue(QRect(panel->x(), panel->y(), panel->width(),panel->height()));
    animation->setEndValue(QRect((width() - panel->width())/2, (height()-panel->height())/2, panel->width(),panel->height()));
    //设置窗口的运动曲线
    animation->setEasingCurve(QEasingCurve(QEasingCurve::OutBounce));
    //播放动画效果
    animation->start();

    //处理窗口信号
    connect(panel,&EndingPanel::continueGame,this,[=](){
        panel->close();
        panel->deleteLater();
        animation->deleteLater();
        ui->btnGroup->selectPanel(ButtonGroup::Empty);
        gameStatusPreces(GameControl::DispatchCard);
        m_bgm->startBGM(80);
    });
}

void GamePanel::initCountDown()
{
    m_countDown = new CountDown(this);
    m_countDown->move((width()-m_countDown->width())/2, (height()-m_countDown->height())/2+30);
    connect(m_countDown,&CountDown::notMuchTime,this,[=](){
        //播放提示音乐
        m_bgm->playAssistMusic(BGMContrl::Alert);
    });
    connect(m_countDown,&CountDown::timeout,this,&GamePanel::onUserPass);
    UserPlayer* userPlayer = m_gameCtl->userPlayer();
    connect(userPlayer,&UserPlayer::startCountDown,this,[=](){
        if(m_gameCtl->pendPlayer() != userPlayer && m_gameCtl->pendPlayer() != nullptr){
            m_countDown->showCountDown();
        }
    });
}

void GamePanel::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter(this);
    painter.drawPixmap(rect(),m_bkImage);
}

void GamePanel::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton){
        QPoint pt = event->pos();
        if(!m_cardRect.contains(pt)){
            m_curSelCard = nullptr;
        }else{
            QList<CardPanel*> list = m_userCards.keys();
            for(int i = 0;i<list.size();++i){
                CardPanel* panel = list.at(i);
                if(m_userCards[panel].contains(pt) && m_curSelCard != panel){
                    //模拟点击这张牌
                    m_curSelCard = panel;
                    panel->clicked();
                }
            }
        }
    }
}
